package com.polyfile.app;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.NotDirectoryException;

public class FileModifier {

	/**
	 * Deletes file by String
	 * 
	 * @param filePath
	 *            - string of the file path, such as "C:/testDir/test.txt"
	 * @throws IOException
	 *             - FileNotFoundException is thrown if file cannot be found,
	 *             IOException is thrown if file is not a directory rather than
	 *             a pure file, or the file cannot be deleted successfully.
	 */
	public static void deleteFile(String filePath) throws IOException {
		deleteFile(new File(filePath));
	}

	/**
	 * Deletes file by file object
	 * 
	 * @param file
	 *            - file object of the file
	 * @throws IOException
	 *             - FileNotFoundException is thrown if file cannot be found,
	 *             IOException is thrown if file is not a directory rather than
	 *             a pure file, or the file cannot be deleted successfully.
	 */
	public static void deleteFile(File file) throws IOException {

		if (!file.exists())
			throw new FileNotFoundException("File path: "
					+ file.getAbsolutePath());

		if (file.isDirectory())
			throw new NotDirectoryException("File \"" + file.getAbsolutePath()
					+ "\" is a directory");

		boolean success = file.delete();// delete the file and get whether it's
										// successful
		if (!success)
			throw new IOException("File \"" + file.getAbsolutePath()
					+ "\" failed to be deleted");

	}

	/**
	 * Makes an empty file by the path of the file without overriding the
	 * original file. Calls overriding method makeFile(filePath, false). If a
	 * file with the same file path already exists, nothing will be done
	 * 
	 * @param filePath
	 *            - string of the file to be made
	 * @throws Exception
	 *             - thrown when there is a directory with the same path
	 *             existing
	 */
	public static void makeFile(String filePath) throws Exception {
		makeFile(new File(filePath));
	}

	/**
	 * Makes an empty file by file object without overriding the original file.
	 * Calls overriding method makeFile(file, false). If a file with the same
	 * file path already exists, nothing will be done
	 * 
	 * @param file
	 *            - file object of the file to be made
	 * @throws Exception
	 *             - thrown when there is a directory with the same path
	 *             existing
	 */
	public static void makeFile(File file) throws Exception {
		makeFile(file, false);
	}

	/**
	 * Makes an empty file by the path of the file, which is a String object.
	 * When the file does not originally exist, the file will be made anyway.
	 * When the file exists, there is an option whether the original file should
	 * be overridden.
	 * 
	 * @param filePath
	 *            - string of the file to be made
	 * @param override
	 *            - whether the file should override the original file
	 * @throws Exception
	 *             - thrown when the make file operation is not successful as
	 *             expected
	 */
	public static void makeFile(String filePath, boolean override)
			throws Exception {
		makeFile(new File(filePath), override);
	}

	/**
	 * Makes an empty file by file object. When the file does not originally
	 * exist, the file will be made anyway. When the file exists, there is an
	 * option whether the original file should be overridden.
	 * 
	 * @param file
	 *            - file object of the file to be made
	 * @param override
	 *            - whether the file should override the original file
	 * @throws Exception
	 *             - thrown when the make file operation is not successful as
	 *             expected
	 */
	public static void makeFile(File file, boolean override) throws Exception {
		// override option is true and file exists
		if (override && file.exists()) {
			if (file.isDirectory())
				throw new Exception("Directory with same path \""
						+ file.getAbsolutePath()
						+ "\" already exists. Make file failed");
			else if (!file.delete()) {
				throw new Exception(
						"File \""
								+ file.getAbsolutePath()
								+ "\" already exists and cannnot be deleted for some reason");
			}
			
			if(!file.createNewFile())
				throw new Exception("File creation failed : " + file.getAbsolutePath());
		}
		// override option is false and file exists
		else if (!override && file.exists()) {
			if (file.isDirectory())
				throw new Exception("Directory with same path \""
						+ file.getAbsolutePath()
						+ "\" already exists. Make file failed");
		}
		// file does not exists
		else {
			if (!file.createNewFile())
				throw new Exception("Unknown exception -- File \""
						+ file.getAbsolutePath()
						+ "\" is not successfully created");
		}
	}

	/**
	 * Deletes the directory in the given path without recursion, i.e. calls
	 * overriding method deleteDir(dirPath, false).
	 * 
	 * @param dirPath
	 *            - string of the directory path
	 * @throws FileNotFoundException
	 *             - thrown if the directory is not found
	 * @throws NotDirectoryException
	 *             - thrown if dir represents a file instead of directory
	 * @throws DirectoryNotEmptyException
	 *             - thrown if the directory is not empty
	 */
	public static void deleteDir(String dirPath) throws FileNotFoundException,
			NotDirectoryException, DirectoryNotEmptyException {
		deleteDir(dirPath, false);
	}

	/**
	 * Deletes the directory represented by the file object without recursion,
	 * i.e. calls overriding method deleteDir(dir, false).
	 * 
	 * @param dir
	 *            - file object representing the directory
	 * @throws FileNotFoundException
	 *             - thrown if the directory is not found
	 * @throws NotDirectoryException
	 *             - thrown if dir represents a file instead of directory
	 * @throws DirectoryNotEmptyException
	 *             - thrown if the directory is not empty
	 */
	public static void deleteDir(File dir) throws FileNotFoundException,
			NotDirectoryException, DirectoryNotEmptyException {
		deleteDir(dir, false);
	}

	/**
	 * Deletes the directory in the given path. There is an option whether the
	 * directory should be deleted recursively.
	 * 
	 * @param dirPath
	 *            - string of the directory path
	 * @param recur
	 *            - whether the directory should be deleted recursively
	 * @throws FileNotFoundException
	 *             - thrown if the directory is not found
	 * @throws NotDirectoryException
	 *             - thrown if dirPath represents a file instead of directory
	 * @throws DirectoryNotEmptyException
	 *             - thrown if the directory is not empty when "recur" is false
	 */
	public static void deleteDir(String dirPath, boolean recur)
			throws FileNotFoundException, NotDirectoryException,
			DirectoryNotEmptyException {
		deleteDir(new File(dirPath), recur);
	}

	/**
	 * Deletes the directory in the given file object. There is an option
	 * whether the directory should be deleted recursively.
	 * 
	 * @param dir
	 *            - file object representing the directory
	 * @param recur
	 *            - whether the directory should be deleted recursively
	 * @throws FileNotFoundException
	 *             - thrown if the directory is not found
	 * @throws NotDirectoryException
	 *             - thrown if dirPath represents a file instead of directory
	 * @throws DirectoryNotEmptyException
	 *             - thrown if the directory is not empty when "recur" is false
	 */
	public static void deleteDir(File dir, boolean recur)
			throws FileNotFoundException, NotDirectoryException,
			DirectoryNotEmptyException {
		if(!dir.exists())
			throw new FileNotFoundException("Direcotry \"" + dir.getAbsolutePath() + "\" does not exist");
		else if(!dir.isDirectory())
			throw new NotDirectoryException("File \"" + dir.getAbsolutePath() + "\" is not a directory");
		else {
			File filesInside[] = dir.listFiles();
			if(!recur && filesInside.length != 0)
				throw new DirectoryNotEmptyException("Directory \"" + dir.getAbsolutePath() + "\" is not empty filesInside: " + filesInside.length);
			else {
			    for (File c : filesInside) {
			    	if(c.isDirectory())
			    		deleteDir(c, true);
			    	else if(!c.delete())
			    		throw new FileNotFoundException("File \"" + c.getAbsolutePath() + "\" failed to be deleted");
			    }
			    dir.delete();//delete the empty directory
			}
			
		}
	}

	/**
	 * Makes the directory by the path given, dirPath. If the directory already
	 * exists, FileAlreadyExistsException will be thrown.
	 * 
	 * @param dirPath
	 *            - string of the directory path
	 * @throws FileAlreadyExistsException
	 *             - thrown if the directory already exists
	 * @throws Exception
	 *             - thrown if the directory is not created successfully for
	 *             unknown reasons
	 */
	public static void makeDir(String dirPath)
			throws FileAlreadyExistsException, Exception {
		makeDir(new File(dirPath));
	}

	/**
	 * Makes the directory by file object, dir, which represents the directory.
	 * If the directory already exists, FileAlreadyExistsException will be
	 * thrown.
	 * 
	 * @param dir
	 *            - file object representing the directory
	 * @throws FileAlreadyExistsException
	 *             - thrown if the directory already exists
	 * @throws Exception
	 *             - thrown if the directory is not created successfully for
	 *             unknown reasons
	 */
	/**
	 * 
	 * @param dir
	 * @throws FileAlreadyExistsException
	 */
	public static void makeDir(File dir) throws FileAlreadyExistsException,
			Exception {
		if (dir.exists())
			throw new FileAlreadyExistsException("File or directory \"" + dir
					+ "\" already exists");
		else {
			if (!dir.mkdirs())
				throw new Exception("Directory \"" + dir.getAbsolutePath()
						+ "\" is not successfully created");
		}
	}

}
